package coreplugin

import (
	"context"
	"gitee.com/go-caipu-team/go-caipu-plugin-sdk/backend"
	sdklog "gitee.com/go-caipu-team/go-caipu-plugin-sdk/backend/log"
	"go-caipu/pkg/plugins"
	"go-caipu/pkg/plugins/backendplugin"

	"go-caipu/pkg/plugins/log"
	"go-caipu/pkg/tsdb/email"
	"go-caipu/pkg/tsdb/testdata"
)

const (
	TestData = "testdata"
	EMAIL    = "email"
	// CaiPuSite = "caipu-site"
	//WORKFLOWAPP = "workflow-app"
)

func init() {
	// Non-optimal global solution to replace plugin SDK default loggers for core plugins.
	sdklog.DefaultLogger = &logWrapper{logger: log.New("plugin.tsdb")}
	backend.Logger = sdklog.DefaultLogger
}

type Registry struct {
	store map[string]backendplugin.PluginFactoryFunc
}

func NewRegistry(store map[string]backendplugin.PluginFactoryFunc) *Registry {
	return &Registry{
		store: store,
	}
}

func ProvideCoreRegistry(td *testdata.Service, email *email.Service) *Registry {
	return NewRegistry(map[string]backendplugin.PluginFactoryFunc{
		TestData: asBackendPlugin(td),
		EMAIL:    asBackendPlugin(email),
		//CaiPuSite: asBackendPlugin(caipuSite),
		// WORKFLOWAPP: asBackendPlugin(workflow),
	})
}
func (cr *Registry) Get(pluginID string) backendplugin.PluginFactoryFunc {
	return cr.store[pluginID]
}
func (cr *Registry) BackendFactoryProvider() func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc {
	return func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc {
		if !p.IsCorePlugin() {
			return nil
		}

		return cr.Get(p.ID)
	}
}
func asBackendPlugin(svc interface{}) backendplugin.PluginFactoryFunc {
	opts := backend.ServeOpts{}
	if queryHandler, ok := svc.(backend.QueryDataHandler); ok {
		opts.QueryDataHandler = queryHandler
	}
	if resourceHandler, ok := svc.(backend.CallResourceHandler); ok {
		opts.CallResourceHandler = resourceHandler
	}
	if streamHandler, ok := svc.(backend.StreamHandler); ok {
		opts.StreamHandler = streamHandler
	}
	if healthHandler, ok := svc.(backend.CheckHealthHandler); ok {
		opts.CheckHealthHandler = healthHandler
	}

	if opts.QueryDataHandler != nil || opts.CallResourceHandler != nil ||
		opts.CheckHealthHandler != nil || opts.StreamHandler != nil {
		return New(opts)
	}

	return nil
}

type logWrapper struct {
	logger log.Logger
}

func (l *logWrapper) Debug(msg string, args ...interface{}) {
	l.logger.Debug(msg, args...)
}

func (l *logWrapper) Info(msg string, args ...interface{}) {
	l.logger.Info(msg, args...)
}

func (l *logWrapper) Warn(msg string, args ...interface{}) {
	l.logger.Warn(msg, args...)
}

func (l *logWrapper) Error(msg string, args ...interface{}) {
	l.logger.Error(msg, args...)
}

func (l *logWrapper) Level() sdklog.Level {
	return sdklog.NoLevel
}

func (l *logWrapper) With(args ...interface{}) sdklog.Logger {
	l.logger = l.logger.New(args...)
	return l
}
